﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net.Sockets;
using System.Threading;
using System.Web;
using DBUtility;
using Fleck;
using Newtonsoft.Json;
using BLL;

namespace IYAKASAPortal.LabourVerify
{
   
    public class DDSocket
    {
        private static Object _lockerObject = new object();
        private static volatile DDSocket instance = null;
        private WebSocketServer m_webSocketServer;
        private List<IWebSocketConnection> m_allSocket;
        private Dictionary<int, DDSocketEntity> m_dicDDEntity;
       

        public static DDSocket GetInstance()
        {
            lock (_lockerObject)
            {
                if (instance == null)
                {
                    CONST_DEFINE_WEB_BLL bll = new CONST_DEFINE_WEB_BLL();
                    var Infos = bll.GetModelList(" Name='DBAddress'");
                    string strIP =  string.Format("ws://{0}:{1}", Infos[0].ValueOfName, 8182);
                    try
                    {
                        instance = new DDSocket();
                        instance.m_webSocketServer = new WebSocketServer(strIP);
                        instance.m_allSocket = new List<IWebSocketConnection>();
                        instance.m_dicDDEntity = new Dictionary<int, DDSocketEntity>();
                        instance.StartServer();
                    }
                    catch (Exception ex)
                    { 
                    }
                }
            }
            return instance;
        }

        private void StartServer()
        {
            if (m_webSocketServer != null)
            {
                m_webSocketServer.Start(socket =>
                {
                    socket.OnOpen = () =>
                    {
                        m_allSocket.Add(socket);
                    };
                    socket.OnClose = () =>
                    {
                        m_allSocket.Remove(socket);
                    };
                    socket.OnMessage = message =>
                    {
                        int line =Convert.ToInt32(message.Replace("dd_", ""));
                        if (m_dicDDEntity.Keys.Contains(line))
                        {
                            m_dicDDEntity[line].DD_Time = DateTime.Now;
                        }
                        
                    };

                });
            }
        }

        private void SendMsg(string msg)
        {
            if (m_allSocket.Count > 0)
            {
                for (int i = 0; i < m_allSocket.Count; i++)
                {
                    if (m_allSocket[i] != null)
                    {
                        m_allSocket[i].Send(msg);
                    }
                }
            }
        }

        private class DDSocketEntity
        {
            public Thread DD_Thread { get; set; }
            public int DD_LineNum { get; set; }
            public bool DD_Status { get; set; }
            public DateTime DD_Time { get; set; }
        }

        public void SendDDMsg(int lineNum)
        {
            if (!m_dicDDEntity.Keys.Contains(lineNum))
            {
                DDSocketEntity entity = new DDSocketEntity();
                entity.DD_LineNum = lineNum;
                entity.DD_Status = true;
                entity.DD_Time = DateTime.Now;
                entity.DD_Thread = new Thread(() =>
                {
                    while (entity.DD_Status)
                    {
                        SendMsg(DataTableToStr(lineNum));
                        if (entity.DD_Time.AddSeconds(20) < DateTime.Now)
                        {
                            entity.DD_Status = false;
                            entity.DD_Thread = null;
                            m_dicDDEntity.Remove(lineNum);
                        }
                        Thread.Sleep(1000);
                    }
                });
                entity.DD_Thread.Start();
                m_dicDDEntity.Add(lineNum, entity);
            }
            
        }

        #region 获取调度状态数据
        /// <summary>
        /// 把datatable转换成json
        /// </summary>
        /// <param name="lineNum"></param>
        /// <returns></returns>
        private string DataTableToStr(int lineNum)
        {
            DataTable dt = GetData(lineNum);
            dt = ReDataTable(dt);

            DataTable dHead = ReBulidHeadTable(lineNum);

            JsonDataEntity entity = new JsonDataEntity();
            entity.Mark = "ZXZT";
            entity.Msg = dt;
            entity.HeadMsg = dHead;
            entity.LineNum = lineNum;

            string str = JsonConvert.SerializeObject(entity);

            return str;
        }

        #region 获取表头数据
        private DataTable GetTableHeadMsg(int lineNum)
        {
            DataTable dt = new DataTable();
            string sql = string.Format("SELECT STA_ID,STA_NAME FROM  INSPECTION_LINE_INFO WHERE LINE_ID = {0}", lineNum);
            DbHelper.GetTable(sql, ref dt);
            return dt;
        }

        private DataTable ReBulidHeadTable(int lineNum)
        {
            DataTable dt = GetTableHeadMsg(lineNum);

            DataTable dTable = new DataTable();
            dTable.Columns.Add("STA_ID", typeof(int));
            dTable.Columns.Add("STA_NAME", typeof(string));

            int i = 1;
            while (dTable.Rows.Count <= dt.Rows.Count && i < 10)
            {
                DataRow dr = dTable.NewRow();
                foreach (DataRow item in dt.Rows)
                {
                    if (Convert.ToInt32(item["STA_ID"]) == i)
                    {
                        dr["STA_ID"] = item["STA_ID"];
                        dr["STA_NAME"] = item["STA_NAME"];
                        dTable.Rows.Add(dr);
                    }
                }
                i++;
            }
            return dTable;
        }
        #endregion

        private DataTable GetData(int lineNum)
        {
            DataTable dt = new DataTable();
            string strSql = "select ID,HPHM,HPZL,HPZLDH,JCXH,ISNULL(GWBH,-1) AS GWBH,JCZT_STATUS,JYXM FROM VEHICLE_DISPATCH where JCZT_STATUS = 2 and jcxh is not null order by JCXH ASC";
            strSql = string.Format("SELECT DISTINCT A.JCLSH,A.HPHM,ISNULL(A.JCZT_STATUS,0) AS JCZT_STATUS, A.AJLSH,ISNULL(A.GWBH,0) AS GWBH,A.GXRQ," +
            "CASE WHEN JCZT_STATUS IN (1,2,3) THEN '是' ELSE '否' END AS IS_LOGIN," 
            + "(SELECT CASE WHEN SUM(CAST( ISNULL(IsSuc,0) AS int)) > 0 THEN '是' ELSE  '否' END FROM NET_JK_RESULT WHERE NET_JK_RESULT.JCLSH = A.JCLSH AND NET_JK_RESULT.JKID = '18C62') AS IS_UPLOAD "
            + "FROM VEHICLE_DISPATCH A"
            + " WHERE A.JCXH = {0} AND CONVERT(VARCHAR(10),A.GXRQ,120) = CONVERT(VARCHAR(10),GETDATE(),120)"
            + " ORDER BY A.GXRQ DESC", lineNum);
            DbHelper.GetTable(strSql, ref dt);
            return dt;
        }

        private DataTable ReDataTable(DataTable dt)
        {

            dt.Columns.Add("ID", typeof(int));
            dt.Columns.Add("OnLine", typeof(int));
            Dictionary<int, int> dic = new Dictionary<int, int>();
            List<int> list = new List<int>();
            int j = 0;
            int i = 1;
            for (int t = 0; t < dt.Rows.Count; t++)
            {
                dt.Rows[t]["ID"] = i;

                if (Convert.ToInt32(dt.Rows[t]["JCZT_STATUS"]) == 2 && t == 0)
                {
                    dt.Rows[t]["OnLine"] = 1;
                    list.Add(Convert.ToInt32(dt.Rows[t]["GWBH"]));

                }
                else if (Convert.ToInt32(dt.Rows[t]["JCZT_STATUS"]) == 2 && t > 0)
                {
                    if (list.Contains(Convert.ToInt32(dt.Rows[t]["GWBH"])))
                    {
                        dt.Rows[t - 1]["OnLine"] = 0;
                    }
                    dt.Rows[t]["OnLine"] = 1;
                }
                else
                {
                    dt.Rows[t]["OnLine"] = 0;
                }

                i++;
            }
            return dt;
        }

        public class JsonDataEntity
        {
            public string Mark
            {
                get;
                set;
            }

            public Object Msg
            {
                get;
                set;
            }

            public Object HeadMsg
            {
                get;
                set;
            }

            public int LineNum
            {
                get;
                set;
            }
        }
        #endregion

    }
}